/*!
 * \file pqueue.h
 * \brief Definition for the pqueue class.
 * \author Vijay Ramesh
 *
 * This is a simple pqueue class.
 */

#ifndef _PQUEUE_H_
#define _PQUEUE_H_
#define TRUE 1
#define FALSE 0

#include <stdbool.h>
#include <unistd.h>

struct pqueue_t;
struct pqnode_t;

typedef int (*funcp)( void* , void* );
typedef struct pqnode_t pqnode_t;
typedef struct pqueue_t pqueue_t;

/*!
 * \brief A pqueue node struct.
 *
 * This is a simple pqueue node class with 2 pointers, next,value.
 * next points to the next node in the pqueue. value is a void pointer to the
 * address of the object being held in the pqueuenode.
 */
struct pqnode_t
{
   pqnode_t *next; /*!< next points to the next node in the pqueue. NULL if at the
                       end of the pqueue.*/
   pqnode_t *prev; /*!< prev points to the next node in the pqueue. NULL if at the
                       end of the pqueue.*/
   void *value;   /*!< value points to the structure held by the pqueue node.
                       NULL if empty.*/
};

/*!
 * \brief A pqueue struct.
 *
 * This is a simple pqueue struct with 2 pointers, front, back and two
 * helper variables, empty, and size. front points to the front of the pqueue.
 * back points to the back of the pqueue. empty is a bool, that is set to false
 * when the pqueue is not empty and true when the pqueue is empty. size is the
 * size of the pqueue.
 */
struct pqueue_t
{
   pqnode_t *front; /*!< front points to the qnode_t at the front of the pqueue.
                        NULL is the pqueue is empty.*/
   pqnode_t *back;  /*!< back poinsts to the qnode_t at the back of the pqueue.
                        NULL if pqueue is empty.*/
   bool empty;     /*!< empty is a boolean that is set to TRUE if the pqueue
                        contains no nodes, and is FALSE if the pqueue contains
                        nodes.*/
   int size;       /*!< size is always set to the size of the pqueue. 0 when
                        pqueue is empty.*/
   funcp less;  /*!< A function pointer which takes two pointers and
                        compares them. This function should return a - number if
                        the first param is greater than the second, 0 if they
                        are equal and a + number if first number if greater than
                        the second number.*/
};

/*!
 * \brief The initializer for the pqueue object.
 *
 * This sets all the pointers in the pqueue object to NULL, size to 0, and empty
 * to true.
 *
 * \param pqueue is the pqueue_t pointer.
 */
void pq_init ( pqueue_t *pqueue, funcp compare );

/*!
 * \brief An enqueue function
 *
 * This pushes a value to the back of the pqueue.
 *
 * \param pqueue is the pqueue_t pointer.
 * \param value is a pointer to the value to be pushed.
 * \return Returns an int, 0 on success and 1 on failure.
 */
int pq_enqueue ( pqueue_t *pqueue, void *value );

/*!
 * \brief A dequeue function
 *
 * This pops the value at the front of the pqueue.
 *
 * \param pqueue is the pqueue_t pointer.
 * \param value is a pointer to the value to be pushed.
 * \return Returns A pointer to the value at the front of the pqueue.
 */
void * pq_dequeue ( pqueue_t *pqueue );

/*!
 * \brief A destroy function
 *
 * This deletes all the space held by pqueue. The values held by each pqueuenode are
 * not deleted.
 *
 * \param pqueue is the pqueue_t pointer.
 */
void pq_destroy ( pqueue_t *pqueue );

/*!
 * \brief A set empty function
 *
 * This sets the empty variable in the pqueue_t by determinig is the pqueue is
 * empty. This is mainly an internal function and never needs to be called upon,
 * although you can call it if you feel like it.
 *
 * \param pqueue is the pqueue_t pointer.
 */
void pq_set_empty ( pqueue_t *pqueue );
#endif
